import java.util.Arrays;

public class AmoebaDivOne {
	private static final int MOD = 1000000007;

	public int count(String[] hexTable) {
		int height = hexTable.length * 2;
		int width = hexTable[0].length() * 2;
		boolean[][] table = new boolean[height][width];
		for (int i = 0; i < height; i += 2) {
			for (int j = 0; j < width; j += 2) {
				char representation = hexTable[i / 2].charAt(j / 2);
				int value;
				if (Character.isDigit(representation))
					value = representation - '0';
				else
					value = representation - 'a' + 10;
				table[i][j] = (value & 1) != 0;
				table[i][j + 1] = (value & 2) != 0;
				table[i + 1][j] = (value & 4) != 0;
				table[i + 1][j + 1] = (value & 8) != 0;
			}
		}
		long[][][] exact = new long[width][width][4];
		int[][][] exactRight = new int[width][width][4];
		int[][][] notExact = new int[width][width][4];
		long answer = 0;
		for (int i = 0; i < width; i++) {
			for (int j = i; j < width; j++) {
				if (table[0][j])
					break;
				for (int k = 0; k < 4; k++)
					exact[i][j][k] = 1;
				answer += exact[i][j][3];
			}
		}
		for (int i = 1; i < height; i++) {
			for (int j = width - 1; j >= 0; j--) {
				for (int k = j; k < width; k++) {
					for (int l = 0; l < 4; l++) {
						exactRight[j][k][l] = (int) exact[j][k][l];
						if (j != k)
							exactRight[j][k][l] += exactRight[j + 1][k][l];
						exactRight[j][k][l] %= MOD;
					}
				}
			}
			for (int j = 0; j < width; j++) {
				for (int k = j; k < width; k++) {
					for (int l = 0; l < 4; l++) {
						notExact[j][k][l] = exactRight[j][k][l];
						if (j != k)
							notExact[j][k][l] += notExact[j][k - 1][l];
						notExact[j][k][l] %= MOD;
					}
				}
			}
			for (long[][] a : exact) {
				for (long[] b : a)
					Arrays.fill(b, 0);
			}
			for (int j = 0; j < width; j++) {
				for (int k = j; k < width; k++) {
					if (table[i][k])
						break;
					exact[j][k][0] = notExact[j][k][0] + 1;
					exact[j][k][1] += notExact[0][k][1] + 1;
					if (j + 1 < width)
						exact[j][k][1] += notExact[j + 1][k][0];
					if (j > 0)
						exact[j][k][1] -= notExact[0][j - 1][1];
					if (j + 1 < width)
						exact[j][k][1] -= notExact[j + 1][k][1];
					exact[j][k][2] += notExact[j][width - 1][2] + 1;
					if (k > 0)
						exact[j][k][2] += notExact[j][k - 1][0];
					if (k + 1 < width)
						exact[j][k][2] -= notExact[k + 1][width - 1][2];
					if (k > 0)
						exact[j][k][2] -= notExact[j][k - 1][2];
					exact[j][k][3] = notExact[0][width - 1][3] + 1;
					if (j < width - 1 && k > 0)
						exact[j][k][3] += notExact[j + 1][k - 1][0] + notExact[j + 1][k - 1][3] - notExact[j + 1][k -
								1][1] - notExact[j + 1][k - 1][2];
					if (j > 0)
						exact[j][k][3] -= notExact[0][j - 1][1];
					if (k + 1 < width)
						exact[j][k][3] -= notExact[k + 1][width - 1][2];
					if (k > 0)
						exact[j][k][3] += notExact[0][k - 1][1] - notExact[0][k - 1][3];
					if (j + 1 < width)
						exact[j][k][3] += notExact[j + 1][width - 1][2] - notExact[j + 1][width - 1][3];
					for (int l = 0; l < 4; l++)
						exact[j][k][l] = (exact[j][k][l] % MOD + MOD) % MOD;
					answer += exact[j][k][3];
				}
			}
		}
		return (int) (answer % MOD);
	}


// BEGIN CUT HERE
	public static void main(String[] args) {
		if (args.length == 0) {
			AmoebaDivOneHarness.run_test(-1);
		} else {
			for (int i=0; i<args.length; ++i)
				AmoebaDivOneHarness.run_test(Integer.valueOf(args[i]));
		}
	}
// END CUT HERE
}

// BEGIN CUT HERE
class AmoebaDivOneHarness {
	public static void run_test(int casenum) {
		if (casenum != -1) {
			if (runTestCase(casenum) == -1)
				System.err.println("Illegal input! Test case " + casenum + " does not exist.");
			return;
		}
		
		int correct = 0, total = 0;
		for (int i=0;; ++i) {
			int x = runTestCase(i);
			if (x == -1) {
				if (i >= 100) break;
				continue;
			}
			correct += x;
			++total;
		}
		
		if (total == 0) {
			System.err.println("No test cases run.");
		} else if (correct < total) {
			System.err.println("Some cases FAILED (passed " + correct + " of " + total + ").");
		} else {
			System.err.println("All " + total + " tests passed!");
		}
	}
	
	static boolean compareOutput(int expected, int result) { return expected == result; }
	static String formatResult(int res) {
		return String.format("%d", res);
	}
	
	static int verifyCase(int casenum, int expected, int received) { 
		System.err.print("Example " + casenum + "... ");
		if (compareOutput(expected, received)) {
			System.err.println("PASSED");
			return 1;
		} else {
			System.err.println("FAILED");
			System.err.println("    Expected: " + formatResult(expected)); 
			System.err.println("    Received: " + formatResult(received)); 
			return 0;
		}
	}

	static int runTestCase(int casenum) {
		switch(casenum) {
		case 0: {
			String[] table            = {"0"};
			int expected__            = 13;

			return verifyCase(casenum, expected__, new AmoebaDivOne().count(table));
		}
		case 1: {
			String[] table            = {"84","21"};
			int expected__            = 72;

			return verifyCase(casenum, expected__, new AmoebaDivOne().count(table));
		}
		case 2: {
			String[] table            = {"e","e"};
			int expected__            = 2;

			return verifyCase(casenum, expected__, new AmoebaDivOne().count(table));
		}
		case 3: {
			String[] table            = {"00"};
			int expected__            = 90;

			return verifyCase(casenum, expected__, new AmoebaDivOne().count(table));
		}

		// custom cases

/*      case 4: {
			String[] table            = ;
			int expected__            = ;

			return verifyCase(casenum, expected__, new AmoebaDivOne().count(table));
		}*/
/*      case 5: {
			String[] table            = ;
			int expected__            = ;

			return verifyCase(casenum, expected__, new AmoebaDivOne().count(table));
		}*/
/*      case 6: {
			String[] table            = ;
			int expected__            = ;

			return verifyCase(casenum, expected__, new AmoebaDivOne().count(table));
		}*/
		default:
			return -1;
		}
	}
}

// END CUT HERE
